TOOL.Category    = "other"
TOOL.Name        = "Explosiver"
TOOL.Command     = nil
TOOL.ConfigName  = ""

-- Tables

local ExplosiveEnts = {}

-- ConVars

TOOL.ClientConVar["Health"]   = "100"
TOOL.ClientConVar["Attached"]   = "0"
TOOL.ClientConVar["chain_reaction"]   = "1"
TOOL.ClientConVar["UseHealth"] = "0"
TOOL.ClientConVar["Multiply"] = "1"
--TOOL.ClientConVar["Global"] = "0"

-- Client

if (CLIENT) then
	language.Add("Tool_explosive_entities_name", "Explosive Entities Tool")
	language.Add("Tool_explosive_entities_desc", "Make something explosive.")
	language.Add("Tool_explosive_entities_0", "Click on an entity to make it explosive.")
	language.Add("Undone_explosive_Entities", "Undone explosive Entity")
end


-- Left click

local SmokeEffectEntities = {}
local function AddSmokeEffect(ent,delay)
        if ValidEntity(ent) then
                SmokeEffectEntities[ent] = {nextcall = CurTime(), delay = delay}
        end
end
 
local function SmokeEffectEntityThink()
        for k,v in pairs(SmokeEffectEntities) do
                if !ValidEntity(k) then 
                        SmokeEffectEntities[k] = nil
                        break
                end
                if v.nextcall < CurTime() then
                        v.nextcall = CurTime() + v.delay						
                        local effectdata = EffectData() 
				
					--	Msg ("local HP = ", k.Breakable.Cur , "\n")
					--	Msg ("local HP = ", k.Breakable.Max , "\n")
					
						local HP = k.explosive.curhp
						local MAXHP = k.explosive.maxhp
						local Low, High = k:WorldSpaceAABB()
						local Center = High - (( High - Low ) * 0.5)
						local vPos = Vector( math.Rand(Low.x,High.x), math.Rand(Low.y,High.y), math.Rand(Low.z,High.z) )
						local SIZE = k:BoundingRadius( )
						effectdata:SetOrigin(vPos)
						effectdata:SetMagnitude( SIZE )
						effectdata:SetScale( HP )
						effectdata:SetRadius( MAXHP )						
						
						
                        effectdata:SetEntity(k)
                        util.Effect( "Smoke_Before_It_Dies", effectdata )
                end
        end
end
 
hook.Add("Think","SmokeEffectEntityThink",SmokeEffectEntityThink)

local function ExtractEntities(inent)
	local ConstrainedEntities = constraint.GetAllConstrainedEntities( inent )
	local entable = {}
	for k, ent in pairs( ConstrainedEntities ) do
		table.insert(entable, ent)
	end
	return entable
end

function TOOL:LeftClick(Trace)
	if (Trace.Entity) then
		if !Trace.Entity:IsValid() or Trace.Entity:IsPlayer() or Trace.HitWorld or Trace.Entity:IsNPC() then
			return nil
		end
	end
	
	
	if(CLIENT) then
		return true
	end

	if(!SERVER) then return false end


	
	local ent = Trace.Entity
	
	local chain = self:GetClientNumber("chain_reaction")
	local multi = self:GetClientNumber("Multiply")
	local hp = self:GetClientNumber("Health")
	local bound = ent:BoundingRadius() * multi
	local col = {}
	local colr, colg, colb, cola = ent:GetColor()
	
	ent.explosive = {}
	
	ent.explosive.colr = colr
	ent.explosive.colg = colg
	ent.explosive.colb = colb
	ent.explosive.cola = cola
	
	ent.explosive.chain = chain //:D GOING DOWN
	
	if(self:GetClientNumber("UseHealth") == 1)then
		ent.explosive.maxhp = hp
		ent.explosive.curhp = hp
	else
		ent.explosive.maxhp = bound
		ent.explosive.curhp = bound
	end
	
	if ent:GetTable().OnTakeDamage then
		local Prev = ent:GetTable().OnTakeDamage
		
		function ent:OnTakeDamage(Info)
			--ErrorNotifyEveryone("Entity took damage "..Info:GetDamage())
			EntityExplosiveDamage(self, Info:GetDamage())
			Prev(self, Info)
		end
	end
	
	
	if !string.find(ent:GetClass(),"wire") then
		if (Wire_CreateOutputs) then
			ent.Outputs = Wire_CreateOutputs(ent, {"Health", "Max", "ConstraintedHealth", "ConstraintedMax"})
		end
		
		if (Wire_TriggerOutput) then
			Wire_TriggerOutput(ent, "Health", ent.explosive.curhp)
			Wire_TriggerOutput(ent, "Max", ent.explosive.maxhp)
			Wire_TriggerOutput(aent, "ConstraintedHealth", ent.explosive.curhp)
			Wire_TriggerOutput(aent, "ConstraintedMax", ent.explosive.maxhp)
		end
	end
	
	
	table.insert(ExplosiveEnts, ent)
	
--	duplicator.RegisterEntityClass( ent:GetClass(), DuplicateExplosiveEntity, "ent" )
	
	
	if(self:GetClientNumber("Attached") == 1)then
		local entable = ExtractEntities(ent)
		for i = 1, #entable do
			local aent = entable[i]
			
			local chain = self:GetClientNumber("chain_reaction")
			local multi = self:GetClientNumber("Multiply")
			local hp = self:GetClientNumber("Health")
			local bound = aent:BoundingRadius() * multi
			local colr, colg, colb, cola = aent:GetColor()
	
			aent.explosive = {}
			
			aent.explosive.entable = entable
			
			aent.explosive.colr = colr
			aent.explosive.colg = colg
			aent.explosive.colb = colb
			aent.explosive.cola = cola
	
			aent.explosive.chain = chain
			
			if(self:GetClientNumber("UseHealth") == 1)then
				aent.explosive.maxhp = hp
				aent.explosive.curhp = hp
			else
				aent.explosive.maxhp = bound
				aent.explosive.curhp = bound
			end
			if aent:GetTable().OnTakeDamage then
				local Prev = aent:GetTable().OnTakeDamage
		
				function aent:OnTakeDamage(Info)
					EntityExplosiveDamage(self, Info:GetDamage())
					Prev(self, Info)
				end
			end
			if (!string.find(aent:GetClass(),"wire") and ent.explosive.entable) then
				if (Wire_CreateOutputs) then
					aent.Outputs = Wire_CreateOutputs(aent, {"Health", "Max", "ConstraintedHealth", "ConstraintedMax"})
				end
				
				local totalmaxhp = 0
				local totalhp = 0
				for k, v in pairs(ent.explosive.entable)do
					if(v.explosive)then
						totalhp = totalhp + v.explosive.curhp
						totalmaxhp = totalmaxhp + v.explosive.maxhp
					end
				end
				
				if (Wire_TriggerOutput) then
					Wire_TriggerOutput(aent, "Health", aent.explosive.curhp)
					Wire_TriggerOutput(aent, "Max", aent.explosive.maxhp)
					Wire_TriggerOutput(aent, "ConstraintedHealth", totalhp)
					Wire_TriggerOutput(aent, "ConstraintedMax", totalmaxhp)
				end
			end
			table.insert(ExplosiveEnts, aent)
			
--			duplicator.RegisterEntityClass( aent:GetClass(), DuplicateExplosiveEntity, "aent" )
		end
		
	end
	
	undo.Create("PropExplosive")
		for i = 1,#ExplosiveEnts do
			undo.AddEntity( ExplosiveEnts[i] )
		end
		undo.SetPlayer( ply )
	undo.Finish()
	--ErrorNotifyEveryone("Entity is now Explosive.")
	
	return true
end

-- Right cick

function TOOL:RightClick(Trace)
	
	return false
end

if SERVER then
	--Entity Replaces
	function ReplaceExplosiveEntity( ent )

		local Explosive = ents.Create("prop_physics")
		Explosive:SetModel(ent:GetModel())
		Explosive:SetPos(ent:GetPos())
		Explosive:SetVelocity(ent:GetVelocity())
		Explosive:SetAngles(ent:GetAngles())
		Explosive:SetColor(0,0,0,0)
		ent:Remove()
		Explosive:Spawn()
		Explosive:Activate()
		return Explosive
	end
	
--[[	function DuplicateExplosiveEntity( ent )
		ErrorNotifyEveryone(ent)
		local Explosive = ents.Create(ent)
		Explosive:SetModel(ent:GetModel())
		Explosive:SetPos(ent:GetPos())
		Explosive:SetVelocity(ent:GetVelocity())
		Explosive:SetAngles(ent:GetAngles())
		Explosive:Spawn()
		Explosive:Activate()
		Explosive.explosive = {}
		Explosive.explosive.colr = ent.explosive.colr
		Explosive.explosive.colg = ent.explosive.colg
		Explosive.explosive.colb = ent.explosive.colb
		Explosive.explosive.cola = ent.explosive.cola
		Explosive.explosive.maxhp = ent.explosive.maxhp
		Explosive.explosive.curhp = ent.explosive.maxhp
		Explosive.explosive.chain = ent.explosive.chain
		return Explosive
	end
	]]
	function EntityExplosiveDamage(ent, damage)
		if damage < 1 then 
			damage = damage * 10000 
			--ErrorNotifyEveryone("damage is less than 0") 
		end
		damage = math.Round(damage)
		ent.explosive.curhp = ent.explosive.curhp - damage
		local SmokeHP = (ent.explosive.curhp / ent.explosive.maxhp) * 100
		
		if SmokeHP < 25 then
			
			AddSmokeEffect(ent,0.1)
			
		end
	--	ErrorNotifyEveryone("Entity took "..damage.." damage.")
		if !string.find(ent:GetClass(),"wire") and ent.explosive.entable then
			local totalmaxhp = 0
			local totalhp = 0
			for k, v in pairs(ent.explosive.entable)do
				if(v.explosive)then
					totalhp = totalhp + v.explosive.curhp
					totalmaxhp = totalmaxhp + v.explosive.maxhp
				end
			end
			for k, t in pairs(ent.explosive.entable)do
				if(t.explosive)then
					Wire_TriggerOutput(t, "ConstraintedHealth", totalhp)
					Wire_TriggerOutput(t, "ConstraintedHealth", totalhp)
					Wire_TriggerOutput(t, "ConstraintedMax", totalmaxhp)
					Wire_TriggerOutput(t, "ConstraintedMax", totalmaxhp)
				end
			end
			Wire_TriggerOutput(ent, "Health", ent.explosive.curhp)
			Wire_TriggerOutput(ent, "Health", ent.explosive.curhp)
			Wire_TriggerOutput(ent, "ConstraintedHealth", totalhp)
			Wire_TriggerOutput(ent, "ConstraintedHealth", totalhp)
			Wire_TriggerOutput(ent, "ConstraintedMax", totalmaxhp)
			Wire_TriggerOutput(ent, "ConstraintedMax", totalmaxhp)
		end
		
		if (ent.explosive.curhp <= 0) and (ent != nil) then
			timer.Simple( math.Rand(0, 0.7), function() ExplosiveEntity(ent) end )
		else
			local stcolr = ent.explosive.colr * (ent.explosive.curhp / ent.explosive.maxhp)
			local stcolg = ent.explosive.colg * (ent.explosive.curhp / ent.explosive.maxhp)
			local stcolb = ent.explosive.colb * (ent.explosive.curhp / ent.explosive.maxhp)
			ent:SetColor( stcolr, stcolg, stcolb, ent.explosive.cola)

		end
	end
	
	function ExplosiveEntity(ent)
		if(ent:IsValid())then
			ExplosiveCreateExplosion(ent)
			ExplosiveCreateDebris(ent)
			local ply = ent:GetOwner()
			if(ply == nil)then
				local ply = ent
			end
			local pos = ent:GetPos()
			local radius = ent:BoundingRadius() * 5
			local repent = ReplaceExplosiveEntity( ent )
			local tiem = math.Rand(0.01, 0.6)
			if(repent != nil) and (ent != nil)then
				if (ent.explosive.chain == 1) then
					timer.Simple(tiem,function() util.BlastDamage( repent, repent, pos, math.Clamp(radius, 0, 500), radius*2) end)
				end //tadaaa
				ent:Remove()
				timer.Simple(tiem+0.01,function() repent:Remove() end)
			end
		end
	end
	
	function ExplosiveCreateExplosion(ent)
		if(ent:IsValid())then
			local Effect = EffectData()
			Effect:SetStart( ent:GetPos() )
			Effect:SetAttachment( 1 )
			Effect:SetOrigin( ent:GetPos() )
			Effect:SetScale( ent:BoundingRadius() )
			Effect:SetMagnitude( 1 )
			util.Effect( "Explosive_Explosion", Effect )
		end
	end
	
	function ExplosiveCreateDebris(ent)
		if(ent:IsValid())then
			local Debris1 = ents.Create("Explosive_Debris")
			Debris1:SetModel(ent:GetModel())
			Debris1:SetPos(ent:GetPos())
			Debris1:SetAngles(ent:GetAngles())
			Debris1:SetVelocity(ent:GetVelocity() + Vector(0,0,-700))
			Debris1:Spawn()
			--constraint.NoCollide( Debris1, ent, 0, 0 ) --Nocollide is broken because it uses a timer and we don't like timers in my town BITCH.
			Debris1:Activate()
			Debris1:GetPhysicsObject():SetMass(ent:GetPhysicsObject():GetMass())			
		end
	end
	
	-- Entity take damage
	
	function DoEntTakeDamageExplosive(Entity, One, Two, Damage)
		if !Entity:IsValid() or Entity:IsPlayer() or Entity:IsNPC() or (Entity.explosive == nil) or (Entity == nil) then
			return nil
		end
		EntityExplosiveDamage(Entity, Damage)
	end
	
	hook.Add("EntityTakeDamage", "EntityTakeDamage", DoEntTakeDamageExplosive)
end


-- Build CPanel

function TOOL.BuildCPanel(Panel)
	Panel:AddControl("Header", {Text = "#Tool_explosive_entities_name", Description	= "#Tool_explosive_entities_desc"})

	Panel:AddControl("Checkbox", {Label = "#Make attached ents explosive", Command = "explosive_entities_Attached"})
	
	Panel:AddControl("Checkbox", {Label = "#Blast Damage", Command = "explosive_entities_chain_reaction"})

	Panel:AddControl("Checkbox", {Label = "#Use specified health", Command = "explosive_entities_UseHealth"})

	Panel:AddControl("Slider", {Label = "#Health", Type	= "Integer", Min = 1, Max = 5000, Command = "explosive_entities_Health"})
	
	Panel:AddControl("Slider", {Label = "#Multiplier", Type	= "Integer", Min = 1, Max = 100, Command = "explosive_entities_Multiply"})
	
	Panel:AddControl("Checkbox", {Label = "#Enable Sunbeams? (Clientside)", Command = "explosive_entities_sunbeams"})
	
	--Panel:AddControl("Checkbox", {Label = "#Global Damage? (Admin Only)", Command = "explosive_entities_Global"})
end